package frontend.pages.reports.charismasynch;

import backend.model.worklog.WorkLogMismatch;
import frontend.components.base.LabelLinkComponent;
import frontend.pages.worklog.daily.DailyWorkLogPage;
import shared.util.CalendarUtils;
import frontend.components.other.UserInputCallableAction;
import org.apache.wicket.Localizer;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.request.cycle.RequestCycle;

import java.io.Serializable;
import java.util.*;

public class DefaultWorkLogMismatchTableTemplate implements Serializable {

    private static final String RESOURCE_KEY_TABLE_HEADER_DATE = "table.header.date";
    private static final String RESOURCE_KEY_TABLE_HEADER_EMPLOYEE = "table.header.employee";
    private static final String RESOURCE_KEY_TABLE_HEADER_IDENTIFICATION_CARD = "table.header.identificationCard";
    private static final String RESOURCE_KEY_TABLE_HEADER_TEAM = "table.header.team";
    private static final String RESOURCE_KEY_TABLE_HEADER_FOREMAN = "table.header.foreman";
    private static final String RESOURCE_KEY_TABLE_HEADER_LOCAL_HOURS = "table.header.localHours";
    private static final String RESOURCE_KEY_TABLE_HEADER_CHARISMA_HOURS = "table.header.charismaHours";

    protected List<IColumn<WorkLogMismatch>> columns = new LinkedList<IColumn<WorkLogMismatch>>();
    protected List<String> header = new LinkedList<String>();

    public static Map<String, Comparator<WorkLogMismatch>> comparatorMap = new HashMap<String, Comparator<WorkLogMismatch>>()
    {{
            put("employee", getByEmployeeComparator());
            put("team", getByTeamComparator());
            put("foreman", getByForemanComparator());
            put("identificationCard", getByIdentificationCardComparator());
            put("date", getByDateComparator());
            put("localHours", getByLocalHoursComparator());
            put("charismaHours", getByCharismaHoursComparator());
        }};

    public DefaultWorkLogMismatchTableTemplate() {
        createColumns();
    }

    public List<IColumn<WorkLogMismatch>> getColumns() {
        return columns;
    }

    public List<String> getHeader() {
        return header;
    }

    protected void createColumns() {
        createDefaultColumns();
    }

    private void createDefaultColumns() {
        columns.add(getDateColumn());
        columns.add(getEmployeeColumn());
        columns.add(getIdentificationCardColumn());
        columns.add(getTeamColumn());
        columns.add(getForemanColumn());
        columns.add(getLocalHoursColumn());
        columns.add(getCharismaHoursColumn());
    }

    protected AbstractColumn<WorkLogMismatch> getEmployeeColumn() {
        String columnName = Localizer.get().getString(RESOURCE_KEY_TABLE_HEADER_EMPLOYEE, null);
        header.add(columnName);
        return new PropertyColumn<WorkLogMismatch>(new Model<String>(columnName), "employee", "employee");
    }

    protected AbstractColumn<WorkLogMismatch> getTeamColumn() {
        String columnName = Localizer.get().getString(RESOURCE_KEY_TABLE_HEADER_TEAM, null);
        header.add(columnName);
        return new AbstractColumn<WorkLogMismatch>(new Model<String>(columnName), "team") {
            @Override
            public void populateItem(Item<ICellPopulator<WorkLogMismatch>> cellItem, String componentId, IModel<WorkLogMismatch> rowModel) {
                WorkLogMismatch workLogMismatch = rowModel.getObject();
                cellItem.add(new Label(componentId, workLogMismatch.getEmployee().getTeam().getDisplayLabel()));
            }
        };
    }

    protected AbstractColumn<WorkLogMismatch> getForemanColumn() {
        String columnName = Localizer.get().getString(RESOURCE_KEY_TABLE_HEADER_FOREMAN, null);
        header.add(columnName);
        return new AbstractColumn<WorkLogMismatch>(new Model<String>(columnName), "foreman") {
            @Override
            public void populateItem(Item<ICellPopulator<WorkLogMismatch>> cellItem, String componentId, IModel<WorkLogMismatch> rowModel) {
                WorkLogMismatch workLogMismatch = rowModel.getObject();
                cellItem.add(new Label(componentId, workLogMismatch.getEmployee().getTeam().getForeman().getDisplayLabel()));
            }
        };
    }

    protected AbstractColumn<WorkLogMismatch> getIdentificationCardColumn() {
        String columnName = Localizer.get().getString(RESOURCE_KEY_TABLE_HEADER_IDENTIFICATION_CARD, null);
        header.add(columnName);
        return new AbstractColumn<WorkLogMismatch>(new Model<String>(columnName), "identificationCard") {
            @Override
            public void populateItem(Item<ICellPopulator<WorkLogMismatch>> cellItem, String componentId, IModel<WorkLogMismatch> rowModel) {
                WorkLogMismatch workLogMismatch = rowModel.getObject();
                cellItem.add(new Label(componentId, workLogMismatch.getEmployee().getIdentificationCard()));
            }
        };
    }

    protected AbstractColumn<WorkLogMismatch> getDateColumn() {
        String columnName = Localizer.get().getString(RESOURCE_KEY_TABLE_HEADER_DATE, null);
        header.add(columnName);
        return new AbstractColumn<WorkLogMismatch>(new Model<String>(columnName), "date") {
            @Override
            public void populateItem(Item<ICellPopulator<WorkLogMismatch>> cellItem, String componentId, IModel<WorkLogMismatch> rowModel) {
                WorkLogMismatch workLogMismatch = rowModel.getObject();
                cellItem.add(new Label(componentId, CalendarUtils.formatDate(workLogMismatch.getDate())));
            }
        };
    }

    protected AbstractColumn<WorkLogMismatch> getLocalHoursColumn() {
        String columnName = Localizer.get().getString(RESOURCE_KEY_TABLE_HEADER_LOCAL_HOURS, null);
        header.add(columnName);
        return new AbstractColumn<WorkLogMismatch>(new Model<String>(columnName), "normalHours") {
            @Override
            public void populateItem(Item<ICellPopulator<WorkLogMismatch>> cellItem, String componentId, IModel<WorkLogMismatch> rowModel) {
                final WorkLogMismatch workLogMismatch = rowModel.getObject();
                int localHours = workLogMismatch.getLocalHours();
                cellItem.add(new LabelLinkComponent(componentId, String.valueOf(localHours), new UserInputCallableAction() {
                    @Override
                    public void call(AjaxRequestTarget target, Object userInput) {
                        Calendar calendar = Calendar.getInstance();
                        calendar.setTime(workLogMismatch.getDate());
                        RequestCycle.get().setResponsePage(new DailyWorkLogPage(workLogMismatch.getEmployee(), calendar));
                    }
                }));
            }
        };
    }

    protected AbstractColumn<WorkLogMismatch> getCharismaHoursColumn() {
        String columnName = Localizer.get().getString(RESOURCE_KEY_TABLE_HEADER_CHARISMA_HOURS, null);
        header.add(columnName);
        return new AbstractColumn<WorkLogMismatch>(new Model<String>(columnName), "charismaHours") {
            @Override
            public void populateItem(Item<ICellPopulator<WorkLogMismatch>> cellItem, String componentId, IModel<WorkLogMismatch> rowModel) {
                WorkLogMismatch workLogMismatch = rowModel.getObject();
                int charismaHours = workLogMismatch.getCharismaHours();
                cellItem.add(new Label(componentId, String.valueOf(charismaHours)));
            }
        };
    }

    protected void removeColumn(int index) {
        columns.remove(index);
        header.remove(index);
    }

    protected static Comparator<WorkLogMismatch> getByDateComparator() {
        return new Comparator<WorkLogMismatch>() {
            @Override
            public int compare(WorkLogMismatch workLogMismatch1, WorkLogMismatch workLogMismatch2) {
                return workLogMismatch1.getDate().compareTo(workLogMismatch2.getDate());
            }
        };
    }

    protected static Comparator<WorkLogMismatch> getByEmployeeComparator() {
        return new Comparator<WorkLogMismatch>() {
            @Override
            public int compare(WorkLogMismatch workLogMismatch1, WorkLogMismatch workLogMismatch2) {
                return workLogMismatch1.getEmployee().compareTo(workLogMismatch2.getEmployee());
            }
        };
    }

    protected static Comparator<WorkLogMismatch> getByTeamComparator() {
        return new Comparator<WorkLogMismatch>() {
            @Override
            public int compare(WorkLogMismatch workLogMismatch1, WorkLogMismatch workLogMismatch2) {
                return workLogMismatch1.getEmployee().getTeam().compareTo(workLogMismatch2.getEmployee().getTeam());
            }
        };
    }

    protected static Comparator<WorkLogMismatch> getByForemanComparator() {
        return new Comparator<WorkLogMismatch>() {
            @Override
            public int compare(WorkLogMismatch workLogMismatch1, WorkLogMismatch workLogMismatch2) {
                return workLogMismatch1.getEmployee().getTeam().getForeman().compareTo(workLogMismatch2.getEmployee().getTeam().getForeman());
            }
        };
    }

    protected static Comparator<WorkLogMismatch> getByIdentificationCardComparator() {
        return new Comparator<WorkLogMismatch>() {
            @Override
            public int compare(WorkLogMismatch workLogMismatch1, WorkLogMismatch workLogMismatch2) {
                return workLogMismatch1.getEmployee().getIdentificationCard().compareTo(workLogMismatch2.getEmployee().getIdentificationCard());
            }
        };
    }

    protected static Comparator<WorkLogMismatch> getByLocalHoursComparator() {
        return new Comparator<WorkLogMismatch>() {
            @Override
            public int compare(WorkLogMismatch workLogMismatch1, WorkLogMismatch workLogMismatch2) {
                return Integer.valueOf(workLogMismatch1.getLocalHours()).compareTo(workLogMismatch2.getLocalHours());
            }
        };
    }

    protected static Comparator<WorkLogMismatch> getByCharismaHoursComparator() {
        return new Comparator<WorkLogMismatch>() {
            @Override
            public int compare(WorkLogMismatch workLogMismatch1, WorkLogMismatch workLogMismatch2) {
                return Integer.valueOf(workLogMismatch1.getCharismaHours()).compareTo(workLogMismatch2.getCharismaHours());
            }
        };
    }
}
